/*
//
//              INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license  agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in  accordance  with the terms of that agreement.
//    Copyright (c) 2007-2008 Intel Corporation. All Rights Reserved.
//
//
*/

#ifndef __UMC_AVS_DEC_MEMORY_PIECE_H
#define __UMC_AVS_DEC_MEMORY_PIECE_H

#include "ippdefs.h"
#include "ipps.h"
#include "umc_structures.h"

namespace UMC
{

class AVSMemory
{
public:
    // Default constructor
    AVSMemory(void)
    {
        m_pbBuffer = (Ipp8u *) 0;
        m_pbBufferEnd = (Ipp8u *) 0;

        m_nAllocated = 0;
        m_nDataSize = 0;
    }
    // Destructor
    virtual
    ~AVSMemory(void)
    {
        Close();
    }

    // Initialize memory piece
    Status Init(size_t nSize)
    {
        if (nSize > m_nAllocated)
        {
            // release the object before initialization
            Close();

            nSize = align_value<Ipp32s> (nSize, 4);
            m_pbBuffer = ippsMalloc_8u((int) nSize);
            if (NULL == m_pbBuffer)
                return UMC_ERR_ALLOC;

            m_pbBufferEnd = m_pbBuffer + nSize;
            m_nAllocated = nSize;
        }

        return UMC_OK;
    }

    // Increase memory piece
    Status Increase(size_t newSize)
    {
        if (newSize > m_nAllocated)
        {
            Ipp8u *pbNewBuffer;
            size_t dataSize = 0;

            // allocate the new buffer
            newSize = align_value<Ipp32s> (newSize, 4);
            pbNewBuffer = ippsMalloc_8u((int) newSize);
            if (NULL == pbNewBuffer)
            {
                return UMC_ERR_ALLOC;
            }

            // copy existing data
            if (m_pbBuffer)
            {
                memcpy(pbNewBuffer, m_pbBuffer, m_nDataSize);
                dataSize = m_nDataSize;
            }

            // release the object
            Close();

            m_pbBuffer = pbNewBuffer;
            m_pbBufferEnd = pbNewBuffer + newSize;

            m_nAllocated = newSize;
            m_nDataSize = dataSize;
        }

        return UMC_OK;
    }

    // Release the object
    Status Close(void)
    {
        if (m_pbBuffer)
        {
            ippsFree(m_pbBuffer);
        }

        m_pbBuffer = (Ipp8u *) 0;
        m_pbBufferEnd = (Ipp8u *) 0;

        m_nAllocated = 0;
        m_nDataSize = 0;

        return UMC_OK;
    }

    // Get pointer to the memory
    inline
    Ipp32u *GetBuffer(void)
    {
        return align_pointer<Ipp32u *> (m_pbBuffer, 4);
    }

    // Get the allocated buffer's size
    inline
    size_t GetSize(void)
    {
        return m_nAllocated;
    }

    // Get the valid data size
    inline
    size_t GetDataSize(void)
    {
        return m_nDataSize;
    }

    // Get the valid data size
    inline
    void SetDataSize(size_t dataSize)
    {
        m_nDataSize = dataSize;
    }

    // Get remaining unused space
    inline
    size_t GetRemainSize(void)
    {
        if (m_pbBuffer)
        {
            return (m_pbBufferEnd - m_pbBuffer - m_nDataSize * sizeof(Ipp32u));
        }
        else
        {
            return 0;
        }
    }

protected:
    Ipp8u *m_pbBuffer;                                          // (Ipp8u *) pointer to the allocated buffer
    Ipp8u *m_pbBufferEnd;                                       // (Ipp8u *) pointer to end of the allocated buffer

    size_t m_nAllocated;                                        // (size_t) size of the allocated buffer
    size_t m_nDataSize;                                         // (size_t) amount of valid data in dwords
};

} // namespace UMC

#endif // __UMC_AVS_DEC_MEMORY_PIECE_H
